#include "io.hpp"
#include "lexer.hpp"
#include "parser.hpp"

#include <fstream>

Variable _bi_printto(vector<Variable>& argv, Environment& env, ostream& out)
{
	Variable ret;
	for(unsigned i=1;i<argv.size();i++) {
		ret=argv[i];
		env.verify(ret);
		switch(ret.type) {
			case tNumeric:
				out.precision((int)env.getvar("__precision__").i);
				out << ret.i;
				break;
			case tAlias:
			case tFunction:
			case tOpcode:
			case tString:
			case tInline:
			case tSpecial:
			case tTypeID:
			case tAliasWithArgc:
			case tAliasWithArgList:
			case tAliasWithTypeList:
				out << ret.str;
				break;
			case tArray: {
				vector<Variable> tmp(2);
				out << env.getvar("__arrprint_start__").str;
				for(unsigned j=0;j<ret.arr.size();j++) {
					tmp[1] = ret.arr[j];
					_bi_printto(tmp,env,out);
					if(j!=ret.arr.size()-1) {
						out << env.getvar("__delimiter__").str;
					}
				}
				out << env.getvar("__arrprint_end__").str;
				break;
			}
			case tCustomType:
				cout << "***ERROR: Invalid print object of custom type `" << ret.str << "`\n";
				break;
			case tError:
			case tNull:
			default:
				cout << "***ERROR: Invalid print object of type `" << vartypeToStr(ret.type) << "`\n";
		}
	}
	return ret;
}

Variable bi_echo(vector<Variable>& argv, Environment& env)
{
	return _bi_printto(argv,env,cout);
}

Variable bi_print(vector<Variable>& argv, Environment& env)
{
	Variable ret = bi_echo(argv,env);
	int argc = (int)argv.size();
	if (argc != 1) {
		bool prints = true;
		for(int i=0;i<argc;i++) {
			if(argv[i].str.length() == 0 && argv[i].type != tArray) {
				prints = false;
			}
		}
		if(prints) {
			cout << "\n";
		}
	}
	return ret;
}

Variable bi_get(vector<Variable>& argv, Environment& env)
{
	UNUSED env;
	Variable ret;
	int argc = (int)argv.size();
	if(argc!=1) {
		throw_error(ERROR_ARGUMENTCOUNT);
	}
	string str="";
	do{
		getline(cin,str);
	}while(str=="");
	ret = str;
	return ret;
}

Variable bi_tell(vector<Variable>& argv, Environment& env)
{
	for(unsigned i=1;i<argv.size();i++) {
		argv[i].tell();
		if(argv[i].type == tVarname) {
			Variable tmp = argv[i];
			env.verify(tmp);
			tmp.tell();
		}
	}
	return Variable();
}
